.NETの10進数、浮動小数点数、および倍数の違いは?
-
03-07-2019 - |
質問
.NETの decimal
、 float
、および double
の違いは何ですか?
誰かがこれらのいずれかを使用するのはいつですか?
解決
float
および double
は floating < em>バイナリポイントタイプ。つまり、これらは次のような数値を表します。
10001.10010110011
2進数と2進小数点の位置は両方とも値内でエンコードされます。
decimal
は浮動小数点 decimal ポイントですタイプ。つまり、これらは次のような数値を表します。
12345.65789
繰り返しますが、小数ポイントの数と位置は両方とも値&#8211;内でエンコードされます。これが、 decimal
を固定小数点型ではなく浮動小数点型のままにするものです。
注意すべき重要なことは、人間は10進形式で非整数を表すことに慣れており、10進表現で正確な結果を期待するということです。すべての10進数が2進浮動小数点で正確に表現できるわけではありません&#8211; 0.1、たとえば&#8211;したがって、バイナリの浮動小数点値を使用すると、実際には0.1の近似値が得られます。浮動小数点を使用する場合も、近似値が得られます&#8211;たとえば、1を3で除算した結果を正確に表すことはできません。
次の場合に使用するもの:
-
「自然に正確な小数」である値の場合
decimal
を使用するとよいでしょう。これは通常、人間が発明した概念に適しています。金銭的価値は最も明白な例ですが、他にもあります。たとえば、ダイバーやアイススケーターに与えられたスコアを考慮してください。 -
実際には正確に測定できない自然の人工物である値の場合、
float
/double
はより多く適切な。たとえば、科学データは通常この形式で表されます。ここでは、元の値は「十分に正確」ではありません。最初から、期待される結果が「10進精度」を維持することは重要ではありません。浮動小数点型は、小数よりも処理がはるかに高速です。
他のヒント
精度が主な違いです。
フロート-7桁(32ビット)
ダブル -15-16桁(64ビット)
10進数 -28-29有効数字(128ビット)
10進数の精度ははるかに高く、通常、高度な精度を必要とする金融アプリケーションで使用されます。 10進数は、double / floatよりもはるかに低速です(一部のテストでは最大20倍)。
DecimalsとFloats / Doublesはキャストなしで比較できませんが、FloatsとDoublesは比較できます。 10進数では、エンコードまたは末尾のゼロも許可されます。
float flt = 1F/3;
double dbl = 1D/3;
decimal dcm = 1M/3;
Console.WriteLine("float: {0} double: {1} decimal: {2}", flt, dbl, dcm);
結果:
float: 0.3333333
double: 0.333333333333333
decimal: 0.3333333333333333333333333333
Decimal構造は、丸めが比較的許容されない精度を必要とする財務計算に厳密に適合しています。ただし、科学的な用途には10進数では不十分です。いくつかの理由があります。
- 物理的な問題や測定されるアーチファクトには実際的な限界があるため、多くの科学計算ではある程度の精度の低下が許容されます。金融機関では精度の低下は許容されません。
- 主に浮動小数点演算はバイナリで行われるため、ほとんどの演算では10進数はfloatおよびdoubleよりもはるかに遅くなりますが、10進数では10進数で処理されます(つまり、floatおよびdoubleはMMX / SSE(小数はソフトウェアで計算されます)。
- Decimalは、より多くの桁数の精度をサポートするという事実にもかかわらず、doubleよりも許容できないほど小さい値範囲を持っています。したがって、Decimalを使用して多くの科学的価値を表すことはできません。
+---------+----------------+---------+----------+---------------------------------------------+
| C# | .Net Framework | Signed? | Bytes | Possible Values |
| Type | (System) type | | Occupied | |
+---------+----------------+---------+----------+---------------------------------------------+
| sbyte | System.Sbyte | Yes | 1 | -128 to 127 |
| short | System.Int16 | Yes | 2 | -32768 to 32767 |
| int | System.Int32 | Yes | 4 | -2147483648 to 2147483647 |
| long | System.Int64 | Yes | 8 | -9223372036854775808 to 9223372036854775807 |
| byte | System.Byte | No | 1 | 0 to 255 |
| ushort | System.Uint16 | No | 2 | 0 to 65535 |
| uint | System.UInt32 | No | 4 | 0 to 4294967295 |
| ulong | System.Uint64 | No | 8 | 0 to 18446744073709551615 |
| float | System.Single | Yes | 4 | Approximately ±1.5 x 10-45 to ±3.4 x 1038 |
| | | | | with 7 significant figures |
| double | System.Double | Yes | 8 | Approximately ±5.0 x 10-324 to ±1.7 x 10308 |
| | | | | with 15 or 16 significant figures |
| decimal | System.Decimal | Yes | 12 | Approximately ±1.0 x 10-28 to ±7.9 x 1028 |
| | | | | with 28 or 29 significant figures |
| char | System.Char | N/A | 2 | Any Unicode character (16 bit) |
| bool | System.Boolean | N/A | 1 / 2 | true or false |
+---------+----------------+---------+----------+---------------------------------------------+
詳細については、以下を参照してください:
http://social.msdn .microsoft.com / Forums / en-US / csharpgeneral / thread / 921a8ffc-9829-4145-bdc9-a96c1ec174a5
float
7桁の精度
double
の精度は約15桁です
decimal
の精度は約28桁です
より高い精度が必要な場合は、floatの代わりにdoubleを使用します。 最新のCPUでは、両方のデータタイプのパフォーマンスはほぼ同じです。フロートを使用する唯一の利点は、使用するスペースが少ないことです。実際に重要なのは、それらの多くを持っている場合だけです。
これは興味深いことがわかりました。 すべてのコンピューター科学者が浮動小数点演算について知っておくべきこと
他の回答やコメントで既に回答された多くの良い(およびいくつかの悪い)情報を繰り返すことはしませんが、フォローアップの質問にはヒントで答えます:
誰かがこれらのいずれかを使用するのはいつですか?
カウント値には小数を使用
測定値の値にはfloat / doubleを使用
いくつかの例:
-
お金(お金を数えるか、お金を測定しますか?)
-
距離(距離をカウントしますか、距離を測定しますか?*)
-
スコア(スコアを数えるか、スコアを測定しますか?)
私たちは常にお金を数え、決して測定すべきではありません。通常、距離を測定します。私たちはしばしばスコアを数えます。
*場合によっては、公称距離と呼ばれるものですが、実際に距離を「カウント」したい場合があります。たとえば、都市までの距離を示す国の標識を扱っているかもしれませんが、それらの距離には10進数(xxx.x km)が1つしか含まれていないことがわかっています。
誰も言及していません
デフォルト設定では、Floats(System.Single)とdoubles(System.Double)は使用しません 10進数(System.Decimal)が常に使用する場合のオーバーフローチェック オーバーフローチェック。
という意味
decimal myNumber = decimal.MaxValue;
myNumber += 1;
OverflowException をスローします。
しかし、これらはしません:
float myNumber = float.MaxValue;
myNumber += 1;
&amp;
double myNumber = double.MaxValue;
myNumber += 1;
前述のように、整数は整数です。 .7、.42、.007など、ポイントを保存することはできません。整数ではない数値を保存する必要がある場合は、異なるタイプの変数が必要です。 double型またはfloat型を使用できます。これらのタイプの変数はまったく同じ方法で設定します。単語 int
を使用する代わりに、 double
または float
と入力します。このように:
float myFloat;
double myDouble;
( float
は「浮動小数点」の略で、末尾にポイントがある数字を意味します。)
2つの違いは、保持できる数字のサイズです。 float
の場合、最大7桁の数字を使用できます。 double
の場合、最大16桁まで使用できます。より正確に言うと、公式サイズは次のとおりです。
float: 1.5 × 10^-45 to 3.4 × 10^38
double: 5.0 × 10^-324 to 1.7 × 10^308
float
は32ビットの数値で、 double
は64ビットの数値です。
新しいボタンをダブルクリックして、コードを取得します。次の3行をボタンコードに追加します。
double myDouble;
myDouble = 0.007;
MessageBox.Show(myDouble.ToString());
プログラムを停止し、コーディングウィンドウに戻ります。次の行を変更します。
myDouble = 0.007;
myDouble = 12345678.1234567;
プログラムを実行し、ダブルボタンをクリックします。メッセージボックスに番号が正しく表示されます。ただし、最後に別の数値を追加すると、C#は再び切り上げまたは切り捨てられます。道徳は、精度が必要な場合、丸めに注意してください!
- Doubleとfloatは、コンパイル時と実行時の両方で例外なく整数ゼロで除算できます。
- 10進数を整数のゼロで割ることはできません。コンパイルすると、常に失敗します。
これは私にとって興味深いスレッドでした。今日、 float
よりも精度が低い decimal
に関する厄介な小さなバグがありました。
C#コードでは、Excelスプレッドシートから数値を読み取り、それらを decimal
に変換し、この decimal
をサービスに送信して、 SQL Server データベース。
Microsoft.Office.Interop.Excel.Range cell = …
object cellValue = cell.Value2;
if (cellValue != null)
{
decimal value = 0;
Decimal.TryParse(cellValue.ToString(), out value);
}
現在、Excelの値のほとんどすべてが であるため、これは見事に機能しました。しかし、一部の非常に小さなExcel値では、 decimal.TryParse
を使用すると、値が完全に失われました。そのような例の1つは
-
cellValue = 0.00006317592
-
Decimal.TryParse(cellValue.ToString()、out value); // 0
を返します
奇妙な解決策は、Excelの値を最初に double
に変換し、次に decimal
に変換することでした:
Microsoft.Office.Interop.Excel.Range cell = …
object cellValue = cell.Value2;
if (cellValue != null)
{
double valueDouble = 0;
double.TryParse(cellValue.ToString(), out valueDouble);
decimal value = (decimal) valueDouble;
…
}
double
の精度は decimal
の精度よりも低いですが、これにより実際に小さな数字が認識されることが保証されます。何らかの理由で、 double.TryParse
は実際にそのような小さな数字を取得できましたが、 decimal.TryParse
はそれらをゼロにします。
奇数。非常に奇妙です。
- float:&#177; 1.5 x 10 ^ -45から&#177; 3.4 x 10 ^ 38(〜7有効数字
- double:&#177; 5.0 x 10 ^ -324から&#177; 1.7 x 10 ^ 308(有効数字15-16)
- 10進数:&#177; 1.0 x 10 ^ -28から&#177; 7.9 x 10 ^ 28(有効数字28-29)
メモリとパフォーマンスの両方が重要なゲームや組み込みシステムなどのアプリケーションでは、floatは高速で、doubleの半分のサイズであるため、通常は数値型の選択肢です。以前は整数が選択の武器でしたが、最新のプロセッサでは浮動小数点のパフォーマンスが整数を上回りました。 10進数は正解です!
Decimal、Double、およびFloat変数タイプは、値を保存する方法が異なります。精度は主な違いで、floatは単精度(32ビット)浮動小数点データ型、doubleは倍精度(64ビット)浮動小数点データ型、decimalは128ビット浮動小数点データ型です。
Float-32ビット(7桁)
ダブル-64ビット(15-16桁)
10進数-128ビット(有効桁数28-29)
詳細... Decimal、Float、Doubleの違い
これらすべてのタイプの問題は、特定の不正確さが存在することです そして、この問題は次の例のように小さな10進数で発生する可能性があること
Dim fMean as Double = 1.18
Dim fDelta as Double = 0.08
Dim fLimit as Double = 1.1
If fMean - fDelta < fLimit Then
bLower = True
Else
bLower = False
End If
質問:bLower変数に含まれる値はどれですか?
回答:32ビットのマシンでは、bLowerにはTRUEが含まれています!!!
DoubleをDecimalに置き換えると、bLowerにはFALSEが含まれます。これが適切な答えです。
doubleでは、問題はfMean-fDelta = 1.09999999999であり、1.1よりも低いことです。
注意:Decimalは高精度のdoubleであり、精度には常に制限があるため、他の数値でも同じ問題が確実に存在する可能性があると思います。
実際、Double、Float、DecimalはCOBOLのBINARY decimalに対応しています!
COBOLで実装されている他の数値型が.Netに存在しないことは残念です。 COBOLを知らない人のために、数値型に続くCOBOLが存在します
BINARY or COMP like float or double or decimal
PACKED-DECIMAL or COMP-3 (2 digit in 1 byte)
ZONED-DECIMAL (1 digit in 1 byte)
簡単な言葉で:
- Decimal、Double、およびFloat変数タイプは、値を保存する方法が異なります。
- 精度は 主な差 (これは単一の差ではないことに注意してください) float は単精度(32ビット)浮動ですポイントデータ型、 double は倍精度(64ビット)浮動小数点データ型、 10進数は128ビット浮動小数点データ型です。
- 概要表:
/==========================================================================================
Type Bits Have up to Approximate Range
/==========================================================================================
float 32 7 digits -3.4 × 10 ^ (38) to +3.4 × 10 ^ (38)
double 64 15-16 digits ±5.0 × 10 ^ (-324) to ±1.7 × 10 ^ (308)
decimal 128 28-29 significant digits ±7.9 x 10 ^ (28) or (1 to 10 ^ (28)
/==========================================================================================
詳細については、こちら、 Float 、 Double 、および 10進数。
これらのそれぞれの主な違いは精度です。
float
は 32ビット
の数値、 double
は 64ビット
の数値、および decimal
は 128ビット
の数字です。